package sample.server;

import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sample.tool.DownLoadImage;
import sample.tool.MysqlDBtool;
import sample.tool.SqliteDBtool;
import sample.tool.Utils;

import java.io.IOException;
import java.sql.*;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

/**
 * @author 杨佳颖
 * @Data 2022-03-21 11:46
 **/
public class jobServer {
    private static Log logger = LogFactory.getLog("mysql");

    private static Log errLog = LogFactory.getLog("programmer");

    private float showNum;//下载完成数量

    private float DownCount = 0f;//总下载量

    public static ExecutorService pool;

    private static final String TABLENAME = "iamge";

    public void timedTask(String dbType,
                          String dburl,
                          String dbuser,
                          String dbpass,
                          String dbport,
                          String dbname,
                          String dbsql,
                          String dbfield,
                          String savepath,
                          String xcs,
                          String serverIP,
                          String replacementLocation,
                          String replaceContent,
                          String cronTime,
                          TextArea log,
                          ProgressBar jindutiao,
                          Label jindutiaowenzi) {
        showNum = 0f;
        int threads = 2;
        int placeNum = 0;

        if (dburl == null || dburl.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "url为空" + "\n");
                }
            });
            return;
        }
        if (dbuser == null || dbuser.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "用户名为空" + "\n");
                }
            });
            return;
        }
        if (dbpass == null || dbpass.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "密码为空" + "\n");
                }
            });
            return;
        }
        if (dbport == null || dbport.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "端口号为空" + "\n");
                }
            });
            return;
        }
        if (dbname == null || dbname.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "数据库名为空" + "\n");
                }
            });
            return;
        }
        if (dbsql == null || dbsql.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "sql语句为空" + "\n");
                }
            });
            return;
        }
        if (dbfield == null || dbfield.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "字段为空" + "\n");
                }
            });
            return;
        }
        if (savepath == null || savepath.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "保存路径为空" + "\n");
                }
            });
            return;
        }

        if (serverIP == null || serverIP.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "请输入IP" + "\n");
                }
            });
            return;
        }
        if (replacementLocation == null || replacementLocation.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "请输入替换位置" + "\n");
                }
            });
            return;
        } else {
            Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
            if (pattern.matcher(replacementLocation).matches()) {
                placeNum = Integer.parseInt(replacementLocation);
            } else {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        log.appendText(new Date() + "请填写整数" + "\n" + "\n");
                    }
                });
                return;
            }
        }
        if (replaceContent == null || replaceContent.equals("")) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "请输入替换内容" + "\n");
                }
            });
            return;
        }

        if (xcs == null || xcs.equals("")) {

        } else {
            Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
            if (pattern.matcher(xcs).matches()) {
                threads = Integer.parseInt(xcs);
            } else {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        log.appendText(new Date() + "请填写整数" + "\n");
                    }
                });
                return;
            }
        }

        List<String> fieldList = Utils.getNameList(dbfield);//字段转为list
        Connection mysqlcon = null;//获取mysql连接
        try {
            mysqlcon = MysqlDBtool.getConnection(dbType, dburl, dbuser, dbpass, dbport, dbname);
        } catch (SQLException throwables) {
            errLog.error(throwables.getMessage());
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "错误，检查配置文件！" + "\n");
                }
            });
            return;
        } catch (ClassNotFoundException e) {
            errLog.error(e.getMessage());
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "数据库驱动加载失败！" + "\n");
                }
            });
            return;
        } catch (IllegalAccessException e) {
            errLog.error(e.getMessage());
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "非法访问异常！" + "\n");
                }
            });
            return;
        } catch (InstantiationException e) {
            errLog.error(e.getMessage());
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "实例化异常！" + "\n");
                }
            });
            return;
        }
        SqliteDBtool.init(TABLENAME, fieldList);//初始化本地数据库
        Connection sqlitecon = SqliteDBtool.getConnection();//获取sqlite连接
        PreparedStatement preparedStatement = null;//mysql
        ResultSet resultSet = null;//mysql
        Statement statement = null;//sqlite
        try {
            preparedStatement = mysqlcon.prepareStatement(dbsql);
            resultSet = preparedStatement.executeQuery();
            sqlitecon.setAutoCommit(false);//sqlite设置不自动提交
            statement = sqlitecon.createStatement();
            int num = 0;
            if (resultSet.isBeforeFirst()) {
                while (resultSet.next()) {
                    String sql = SqliteDBtool.getSql(TABLENAME, fieldList, resultSet);//获取并生成sql语句
                    statement.addBatch(sql);
                    if (num % 5000 == 0) {
                        statement.executeBatch();
                    }
                    num++;
                }
                statement.executeBatch();
                sqlitecon.commit();
            } else {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        log.appendText(new Date() + dbsql + ";查询无数据" + "\n");
                    }
                });
            }

        } catch (SQLException throwables) {
            errLog.error(throwables.getMessage());
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    log.appendText(new Date() + "错误，请检查错误日志" + "\n");
                }
            });
            try {
                sqlitecon.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return;
        } finally {
            MysqlDBtool.close(mysqlcon, preparedStatement, resultSet);
            SqliteDBtool.close(sqlitecon, statement, null);
        }
        if (pool == null) {
            pool = Executors.newFixedThreadPool(threads);
        } else {
            if (pool.isShutdown()) {
                pool = Executors.newFixedThreadPool(threads);
            }
        }
        int finalThreads = threads;
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                log.appendText(new Date() + "开启线程s数量:" + finalThreads + "\n");
            }
        });
        down(fieldList, savepath, serverIP, placeNum, replaceContent, jindutiao, log, jindutiaowenzi);
    }


    /**
     * 下载
     *
     * @param fieldList 字段数组
     * @param savepath  保存路径
     * @param serverIP  ip
     * @param placeNum  替换位置数
     * @param content   替换内容
     */
    private void down(List<String> fieldList,
                      String savepath,
                      String serverIP,
                      int placeNum,
                      String content,
                      ProgressBar jindutiao,
                      TextArea log,
                      Label jindutiaowenzi) {
        final int[] successNum = {0};
        final int[] errorNum = {0};
        Long starttime = System.currentTimeMillis();
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                log.clear();
                jindutiao.setProgress(0);
                //更新JavaFX的主线程的代码放在此处
                jindutiao.setProgress(ProgressBar.INDETERMINATE_PROGRESS);
            }
        });

        //读取本地数据库
        Connection sqliteCon = SqliteDBtool.getConnection();
        Statement selectStatement = null;
        ResultSet set = null;
        String count = "select count(1) from " + TABLENAME;
        String selectSql = "select * from " + TABLENAME;
        try {
            selectStatement = sqliteCon.createStatement();//查询本地数据库数据
            set = selectStatement.executeQuery(count);
            DownCount = set.getFloat(1);
            if (DownCount > 0) {
                //如果有数据
                set = selectStatement.executeQuery(selectSql);
                if (set.isBeforeFirst()) {
                    while (set.next()) {
                        for (int i = 0; i < fieldList.size(); i++) {
                            String imageUrl = fieldList.get(i);
                            String url = set.getString(imageUrl);
                            int finalI = i;
                            pool.execute(() -> {
                                try {
                                    if (url != null && !url.equals("") && !url.equals("null")) {
                                        String readUrl = serverIP + url;//读取图片路径
                                        String save = savepath + "\\" + Utils.replaceUrl(url, placeNum, content);//保存路径
                                        String fileName = Utils.getName(url);//获取文件名
                                        DownLoadImage.downImages(save, readUrl, fileName);
                                        Platform.runLater(new Runnable() {
                                            @Override
                                            public void run() {
                                                log.appendText(new Date() + "复制:" + readUrl + "成功\n");
                                                successNum[0]++;
                                            }
                                        });
                                    }
                                } catch (IOException e) {
                                    Platform.runLater(new Runnable() {
                                        @Override
                                        public void run() {
                                            try {
                                                String readUrl = serverIP + url;//读取图片路径
                                                String save = savepath + "\\" + Utils.replaceUrl(url, placeNum, content);//保存路径
                                                String fileName = Utils.getName(url);//获取文件名
                                                DownLoadImage.downImages(save, readUrl, fileName);
                                                Platform.runLater(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        log.appendText(new Date() + "复制:" + readUrl + "成功\n");
                                                        successNum[0]++;
                                                    }
                                                });
                                            } catch (IOException ioException) {
                                                logger.info("失败:" + serverIP + url);
                                                log.appendText(new Date() + "失败:" + serverIP + url + "\n");
                                                errorNum[0]++;
                                            }

                                        }
                                    });
                                }
                                if (finalI == (fieldList.size() - 1)) {
                                    Platform.runLater(new Runnable() {
                                        @Override
                                        public void run() {
                                            float num = (float) (showNum % DownCount);
                                            num += 1;
                                            showNum++;
                                            jindutiao.setProgress(num / DownCount);
                                            jindutiaowenzi.setText("完成" + Math.round(showNum) + ",总计" + Math.round(DownCount));
                                            if (showNum == DownCount) {
                                                logger.info("任务结束");
                                                Long endstart = System.currentTimeMillis();
                                                log.appendText(new Date() + "复制完成,本次耗时" + (endstart - starttime) + "ms,成功" + successNum[0] + "条，失败" + errorNum[0] + "条\n");
                                            }
                                        }
                                    });
                                }

                            });


                        }
                    }

                } else {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            log.appendText(new Date() + "无数据" + "\n");
                        }
                    });

                }
            } else {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        log.appendText(new Date() + "无数据1" + "\n");
                    }
                });
            }
        } catch (SQLException throwables) {
            errLog.error(throwables.getMessage());
        } finally {
            SqliteDBtool.close(sqliteCon, selectStatement, set);
        }
    }

}
